package org.convallaria.system.biz.util;

import org.convallaria.framework.common.constants.sys.MenuConstants;
import org.convallaria.system.biz.entity.SysMenu;

/**
 * 系统菜单工具类
 * 
 * 功能特性：
 * - 提供菜单相关的业务逻辑判断方法
 * - 提供菜单类型、状态等描述信息
 * - 提供菜单数据验证方法
 * - 提供菜单信息格式化方法
 * - 提供菜单树结构操作方法
 * 
 * 设计原则：
 * - 纯静态方法，无状态
 * - 业务逻辑与实体类分离
 * - 便于单元测试
 * - 提高代码可维护性
 * 
 * @author convallaria
 * @since 1.0.0
 */
public class SysMenuUtils {

    // ==================== 菜单类型判断方法 ====================

    /**
     * 判断是否为目录
     * 
     * @param menu 菜单对象
     * @return true=目录，false=其他
     */
    public static boolean isDirectory(SysMenu menu) {
        if (menu == null || menu.getMenuType() == null) {
            return false;
        }
        return MenuConstants.isDirectory(menu.getMenuType());
    }

    /**
     * 判断是否为菜单
     * 
     * @param menu 菜单对象
     * @return true=菜单，false=其他
     */
    public static boolean isMenu(SysMenu menu) {
        if (menu == null || menu.getMenuType() == null) {
            return false;
        }
        return MenuConstants.isMenu(menu.getMenuType());
    }

    /**
     * 判断是否为按钮
     * 
     * @param menu 菜单对象
     * @return true=按钮，false=其他
     */
    public static boolean isButton(SysMenu menu) {
        if (menu == null || menu.getMenuType() == null) {
            return false;
        }
        return MenuConstants.isButton(menu.getMenuType());
    }

    /**
     * 判断菜单类型是否有效
     * 
     * @param menuType 菜单类型
     * @return true=有效，false=无效
     */
    public static boolean isValidMenuType(String menuType) {
        return MenuConstants.isValidMenuType(menuType);
    }

    // ==================== 菜单状态判断方法 ====================

    /**
     * 判断菜单是否正常状态
     * 
     * @param menu 菜单对象
     * @return true=正常，false=停用
     */
    public static boolean isNormal(SysMenu menu) {
        if (menu == null || menu.getStatus() == null) {
            return false;
        }
        return MenuConstants.MENU_STATUS_NORMAL.equals(menu.getStatus());
    }

    /**
     * 判断菜单是否停用状态
     * 
     * @param menu 菜单对象
     * @return true=停用，false=正常
     */
    public static boolean isDisabled(SysMenu menu) {
        if (menu == null || menu.getStatus() == null) {
            return false;
        }
        return MenuConstants.MENU_STATUS_DISABLED.equals(menu.getStatus());
    }

    /**
     * 判断菜单状态是否有效
     * 
     * @param status 状态值
     * @return true=有效，false=无效
     */
    public static boolean isValidStatus(String status) {
        return MenuConstants.isValidMenuStatus(status);
    }

    // ==================== 菜单显示状态判断方法 ====================

    /**
     * 判断菜单是否显示
     * 
     * @param menu 菜单对象
     * @return true=显示，false=隐藏
     */
    public static boolean isVisible(SysMenu menu) {
        if (menu == null || menu.getVisible() == null) {
            return false;
        }
        return MenuConstants.isVisible(menu.getVisible());
    }

    /**
     * 判断菜单是否隐藏
     * 
     * @param menu 菜单对象
     * @return true=隐藏，false=显示
     */
    public static boolean isHidden(SysMenu menu) {
        if (menu == null || menu.getVisible() == null) {
            return false;
        }
        return MenuConstants.MENU_VISIBLE_HIDE.equals(menu.getVisible());
    }

    /**
     * 判断菜单显示状态是否有效
     * 
     * @param visible 显示状态值
     * @return true=有效，false=无效
     */
    public static boolean isValidVisible(String visible) {
        return MenuConstants.isValidMenuVisible(visible);
    }

    // ==================== 外链和缓存判断方法 ====================

    /**
     * 判断是否为外链
     * 
     * @param menu 菜单对象
     * @return true=外链，false=内链
     */
    public static boolean isFrame(SysMenu menu) {
        if (menu == null || menu.getIsFrame() == null) {
            return false;
        }
        return MenuConstants.isFrame(menu.getIsFrame());
    }

    /**
     * 判断是否缓存
     * 
     * @param menu 菜单对象
     * @return true=缓存，false=不缓存
     */
    public static boolean isCache(SysMenu menu) {
        if (menu == null || menu.getIsCache() == null) {
            return false;
        }
        return MenuConstants.isCache(menu.getIsCache());
    }

    /**
     * 判断外链标识是否有效
     * 
     * @param isFrame 外链标识值
     * @return true=有效，false=无效
     */
    public static boolean isValidIsFrame(Integer isFrame) {
        return MenuConstants.isValidIsFrame(isFrame);
    }

    /**
     * 判断缓存标识是否有效
     * 
     * @param isCache 缓存标识值
     * @return true=有效，false=无效
     */
    public static boolean isValidIsCache(Integer isCache) {
        return MenuConstants.isValidIsCache(isCache);
    }

    // ==================== 层级关系判断方法 ====================

    /**
     * 判断是否为根菜单
     * 
     * @param menu 菜单对象
     * @return true=根菜单，false=子菜单
     */
    public static boolean isRootMenu(SysMenu menu) {
        if (menu == null) {
            return false;
        }
        return MenuConstants.isRootMenu(menu.getParentId());
    }

    /**
     * 判断是否为子菜单
     * 
     * @param menu 菜单对象
     * @return true=子菜单，false=根菜单
     */
    public static boolean isChildMenu(SysMenu menu) {
        return !isRootMenu(menu);
    }

    /**
     * 判断两个菜单是否为父子关系
     * 
     * @param parentMenu 父菜单
     * @param childMenu 子菜单
     * @return true=父子关系，false=非父子关系
     */
    public static boolean isParentChild(SysMenu parentMenu, SysMenu childMenu) {
        if (parentMenu == null || childMenu == null) {
            return false;
        }
        return parentMenu.getMenuId().equals(childMenu.getParentId());
    }

    // ==================== 数据验证方法 ====================

    /**
     * 验证菜单信息是否完整
     * 
     * @param menu 菜单对象
     * @return true=完整，false=不完整
     */
    public static boolean isValidMenu(SysMenu menu) {
        if (menu == null) {
            return false;
        }
        
        // 必填字段验证
        if (!MenuConstants.isValidMenuName(menu.getMenuName())) {
            return false;
        }
        
        // 菜单类型验证
        if (!isValidMenuType(menu.getMenuType())) {
            return false;
        }
        
        // 状态验证
        if (!isValidStatus(menu.getStatus())) {
            return false;
        }
        
        // 显示状态验证
        if (!isValidVisible(menu.getVisible())) {
            return false;
        }
        
        // 外链标识验证
        if (!isValidIsFrame(menu.getIsFrame())) {
            return false;
        }
        
        // 缓存标识验证
        if (!isValidIsCache(menu.getIsCache())) {
            return false;
        }
        
        // 路由地址验证
        if (!MenuConstants.isValidPath(menu.getPath())) {
            return false;
        }
        
        // 组件路径验证
        if (!MenuConstants.isValidComponent(menu.getComponent())) {
            return false;
        }
        
        // 权限标识验证
        if (!MenuConstants.isValidPerms(menu.getPerms())) {
            return false;
        }
        
        // 显示顺序验证
        if (!MenuConstants.isValidOrderNum(menu.getOrderNum())) {
            return false;
        }
        
        return true;
    }

    /**
     * 验证菜单名称格式
     * 
     * @param menuName 菜单名称
     * @return true=有效，false=无效
     */
    public static boolean isValidMenuName(String menuName) {
        return MenuConstants.isValidMenuName(menuName);
    }

    /**
     * 验证路由地址格式
     * 
     * @param path 路由地址
     * @return true=有效，false=无效
     */
    public static boolean isValidPath(String path) {
        return MenuConstants.isValidPath(path);
    }

    /**
     * 验证组件路径格式
     * 
     * @param component 组件路径
     * @return true=有效，false=无效
     */
    public static boolean isValidComponent(String component) {
        return MenuConstants.isValidComponent(component);
    }

    /**
     * 验证权限标识格式
     * 
     * @param perms 权限标识
     * @return true=有效，false=无效
     */
    public static boolean isValidPerms(String perms) {
        return MenuConstants.isValidPerms(perms);
    }

    /**
     * 验证显示顺序格式
     * 
     * @param orderNum 显示顺序
     * @return true=有效，false=无效
     */
    public static boolean isValidOrderNum(Integer orderNum) {
        return MenuConstants.isValidOrderNum(orderNum);
    }

    // ==================== 格式化方法 ====================

    /**
     * 格式化菜单显示名称
     * 
     * @param menu 菜单对象
     * @return 格式化后的显示名称
     */
    public static String formatDisplayName(SysMenu menu) {
        if (menu == null) {
            return "未知菜单";
        }
        
        String displayName = menu.getMenuName();
        if (displayName == null || displayName.trim().isEmpty()) {
            return "未知菜单";
        }
        
        return displayName;
    }

    /**
     * 格式化菜单完整信息
     * 
     * @param menu 菜单对象
     * @return 格式化后的完整信息
     */
    public static String formatMenuInfo(SysMenu menu) {
        if (menu == null) {
            return "菜单信息为空";
        }
        
        StringBuilder sb = new StringBuilder();
        sb.append("菜单ID: ").append(menu.getMenuId()).append(", ");
        sb.append("菜单名称: ").append(menu.getMenuName()).append(", ");
        sb.append("菜单类型: ").append(getMenuTypeDesc(menu.getMenuType())).append(", ");
        sb.append("状态: ").append(getStatusDesc(menu.getStatus())).append(", ");
        sb.append("显示状态: ").append(getVisibleDesc(menu.getVisible())).append(", ");
        sb.append("父菜单ID: ").append(menu.getParentId());
        
        return sb.toString();
    }

    /**
     * 格式化菜单路径信息
     * 
     * @param menu 菜单对象
     * @return 格式化后的路径信息
     */
    public static String formatPathInfo(SysMenu menu) {
        if (menu == null) {
            return "路径信息为空";
        }
        
        StringBuilder sb = new StringBuilder();
        sb.append("路由地址: ").append(menu.getPath()).append(", ");
        sb.append("组件路径: ").append(menu.getComponent()).append(", ");
        sb.append("路由参数: ").append(menu.getQuery()).append(", ");
        sb.append("外链标识: ").append(getIsFrameDesc(menu.getIsFrame()));
        
        return sb.toString();
    }

    /**
     * 格式化菜单权限信息
     * 
     * @param menu 菜单对象
     * @return 格式化后的权限信息
     */
    public static String formatPermissionInfo(SysMenu menu) {
        if (menu == null) {
            return "权限信息为空";
        }
        
        StringBuilder sb = new StringBuilder();
        sb.append("权限标识: ").append(menu.getPerms()).append(", ");
        sb.append("菜单图标: ").append(menu.getIcon()).append(", ");
        sb.append("显示顺序: ").append(menu.getOrderNum()).append(", ");
        sb.append("缓存标识: ").append(getIsCacheDesc(menu.getIsCache()));
        
        return sb.toString();
    }

    // ==================== 描述信息方法 ====================

    /**
     * 获取菜单类型描述
     * 
     * @param menuType 菜单类型
     * @return 菜单类型描述
     */
    public static String getMenuTypeDesc(String menuType) {
        return MenuConstants.getMenuTypeDesc(menuType);
    }

    /**
     * 获取菜单状态描述
     * 
     * @param status 状态值
     * @return 状态描述
     */
    public static String getStatusDesc(String status) {
        return MenuConstants.getMenuStatusDesc(status);
    }

    /**
     * 获取菜单显示状态描述
     * 
     * @param visible 显示状态值
     * @return 显示状态描述
     */
    public static String getVisibleDesc(String visible) {
        return MenuConstants.getMenuVisibleDesc(visible);
    }

    /**
     * 获取外链标识描述
     * 
     * @param isFrame 外链标识值
     * @return 外链标识描述
     */
    public static String getIsFrameDesc(Integer isFrame) {
        return MenuConstants.getIsFrameDesc(isFrame);
    }

    /**
     * 获取缓存标识描述
     * 
     * @param isCache 缓存标识值
     * @return 缓存标识描述
     */
    public static String getIsCacheDesc(Integer isCache) {
        return MenuConstants.getIsCacheDesc(isCache);
    }

    // ==================== 业务逻辑方法 ====================

    /**
     * 判断菜单是否可以删除
     * 
     * @param menu 菜单对象
     * @return true=可以删除，false=不能删除
     */
    public static boolean canDelete(SysMenu menu) {
        if (menu == null) {
            return false;
        }
        
        // 根菜单不能删除
        if (isRootMenu(menu)) {
            return false;
        }
        
        // 停用的菜单可以删除
        return isDisabled(menu);
    }

    /**
     * 判断菜单是否可以编辑
     * 
     * @param menu 菜单对象
     * @return true=可以编辑，false=不能编辑
     */
    public static boolean canEdit(SysMenu menu) {
        if (menu == null) {
            return false;
        }
        
        // 所有菜单都可以编辑
        return true;
    }

    /**
     * 判断菜单是否可以使用
     * 
     * @param menu 菜单对象
     * @return true=可以使用，false=不能使用
     */
    public static boolean canUse(SysMenu menu) {
        if (menu == null) {
            return false;
        }
        
        // 正常状态且显示的菜单可以使用
        return isNormal(menu) && isVisible(menu);
    }

    /**
     * 判断菜单是否为空
     * 
     * @param menu 菜单对象
     * @return true=为空，false=不为空
     */
    public static boolean isEmpty(SysMenu menu) {
        if (menu == null) {
            return true;
        }
        
        return (menu.getMenuName() == null || menu.getMenuName().trim().isEmpty());
    }

    /**
     * 判断菜单是否有效（非空且格式正确）
     * 
     * @param menu 菜单对象
     * @return true=有效，false=无效
     */
    public static boolean isValid(SysMenu menu) {
        return !isEmpty(menu) && isValidMenu(menu);
    }

    /**
     * 判断菜单名称是否重复
     * 
     * @param menu1 菜单对象1
     * @param menu2 菜单对象2
     * @return true=重复，false=不重复
     */
    public static boolean isMenuNameDuplicate(SysMenu menu1, SysMenu menu2) {
        if (menu1 == null || menu2 == null) {
            return false;
        }
        
        String name1 = menu1.getMenuName();
        String name2 = menu2.getMenuName();
        
        if (name1 == null || name2 == null) {
            return false;
        }
        
        return name1.equals(name2);
    }

    /**
     * 判断权限标识是否重复
     * 
     * @param menu1 菜单对象1
     * @param menu2 菜单对象2
     * @return true=重复，false=不重复
     */
    public static boolean isPermsDuplicate(SysMenu menu1, SysMenu menu2) {
        if (menu1 == null || menu2 == null) {
            return false;
        }
        
        String perms1 = menu1.getPerms();
        String perms2 = menu2.getPerms();
        
        if (perms1 == null || perms2 == null) {
            return false;
        }
        
        return perms1.equals(perms2);
    }

    /**
     * 清理菜单名称（去除多余空格）
     * 
     * @param menu 菜单对象
     * @return 清理后的菜单名称
     */
    public static String cleanMenuName(SysMenu menu) {
        if (menu == null || menu.getMenuName() == null) {
            return "";
        }
        return MenuConstants.cleanMenuName(menu.getMenuName());
    }

    /**
     * 清理路由地址（去除多余空格）
     * 
     * @param menu 菜单对象
     * @return 清理后的路由地址
     */
    public static String cleanPath(SysMenu menu) {
        if (menu == null || menu.getPath() == null) {
            return "";
        }
        return MenuConstants.cleanPath(menu.getPath());
    }

    /**
     * 清理组件路径（去除多余空格）
     * 
     * @param menu 菜单对象
     * @return 清理后的组件路径
     */
    public static String cleanComponent(SysMenu menu) {
        if (menu == null || menu.getComponent() == null) {
            return "";
        }
        return MenuConstants.cleanComponent(menu.getComponent());
    }

    /**
     * 清理权限标识（去除多余空格）
     * 
     * @param menu 菜单对象
     * @return 清理后的权限标识
     */
    public static String cleanPerms(SysMenu menu) {
        if (menu == null || menu.getPerms() == null) {
            return "";
        }
        return MenuConstants.cleanPerms(menu.getPerms());
    }

    /**
     * 获取菜单层级深度
     * 
     * @param menu 菜单对象
     * @return 层级深度，0表示根菜单
     */
    public static int getMenuDepth(SysMenu menu) {
        if (menu == null) {
            return 0;
        }
        
        int depth = 0;
        Long parentId = menu.getParentId();
        
        while (parentId != null && !MenuConstants.DEFAULT_PARENT_ID.equals(parentId)) {
            depth++;
            if (depth > MenuConstants.MAX_MENU_DEPTH) {
                break; // 防止无限循环
            }
            // 这里需要根据实际业务逻辑来获取父菜单
            // 由于是工具类，不依赖数据库查询，所以这里只是示例
            parentId = null; // 实际实现中需要查询父菜单
        }
        
        return depth;
    }

    /**
     * 判断菜单是否在指定层级范围内
     * 
     * @param menu 菜单对象
     * @param maxDepth 最大层级深度
     * @return true=在范围内，false=超出范围
     */
    public static boolean isWithinDepth(SysMenu menu, int maxDepth) {
        if (menu == null) {
            return false;
        }
        
        int depth = getMenuDepth(menu);
        return depth <= maxDepth;
    }
}
